/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.hpvas.persistence.dao;

import edu.hpvas.persistence.entity.Owner;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import edu.hpvas.persistence.entity.Person;
import edu.hpvas.persistence.entity.Pet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 *
 * @author raider
 */
public class OwnerDAO implements Serializable {

    public OwnerDAO() {
        this.emf = Persistence.createEntityManagerFactory("HPVAS");
    }
    private EntityManagerFactory emf;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Owner owner) throws Exception {
        if (owner.getPetCollection() == null) {
            owner.setPetCollection(new ArrayList<Pet>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Person idPerson = owner.getIdPerson();
            if (idPerson != null) {
                idPerson = em.getReference(idPerson.getClass(), idPerson.getId());
                owner.setIdPerson(idPerson);
            }
            Collection<Pet> attachedPetCollection = new ArrayList<Pet>();
            for (Pet petCollectionPetToAttach : owner.getPetCollection()) {
                petCollectionPetToAttach = em.getReference(petCollectionPetToAttach.getClass(), petCollectionPetToAttach.getId());
                attachedPetCollection.add(petCollectionPetToAttach);
            }
            owner.setPetCollection(attachedPetCollection);
            em.persist(owner);
            if (idPerson != null) {
                idPerson.getOwnerCollection().add(owner);
                idPerson = em.merge(idPerson);
            }
            for (Pet petCollectionPet : owner.getPetCollection()) {
                Owner oldIdOwnerOfPetCollectionPet = petCollectionPet.getIdOwner();
                petCollectionPet.setIdOwner(owner);
                petCollectionPet = em.merge(petCollectionPet);
                if (oldIdOwnerOfPetCollectionPet != null) {
                    oldIdOwnerOfPetCollectionPet.getPetCollection().remove(petCollectionPet);
                    oldIdOwnerOfPetCollectionPet = em.merge(oldIdOwnerOfPetCollectionPet);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findOwner(owner.getId()) != null) {
                System.out.println("Owner " + owner + " already exists.");
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Owner owner) throws Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Owner persistentOwner = em.find(Owner.class, owner.getId());
            Person idPersonOld = persistentOwner.getIdPerson();
            Person idPersonNew = owner.getIdPerson();
            Collection<Pet> petCollectionOld = persistentOwner.getPetCollection();
            Collection<Pet> petCollectionNew = owner.getPetCollection();
            if (idPersonNew != null) {
                idPersonNew = em.getReference(idPersonNew.getClass(), idPersonNew.getId());
                owner.setIdPerson(idPersonNew);
            }
            Collection<Pet> attachedPetCollectionNew = new ArrayList<Pet>();
            for (Pet petCollectionNewPetToAttach : petCollectionNew) {
                petCollectionNewPetToAttach = em.getReference(petCollectionNewPetToAttach.getClass(), petCollectionNewPetToAttach.getId());
                attachedPetCollectionNew.add(petCollectionNewPetToAttach);
            }
            petCollectionNew = attachedPetCollectionNew;
            owner.setPetCollection(petCollectionNew);
            owner = em.merge(owner);
            if (idPersonOld != null && !idPersonOld.equals(idPersonNew)) {
                idPersonOld.getOwnerCollection().remove(owner);
                idPersonOld = em.merge(idPersonOld);
            }
            if (idPersonNew != null && !idPersonNew.equals(idPersonOld)) {
                idPersonNew.getOwnerCollection().add(owner);
                idPersonNew = em.merge(idPersonNew);
            }
            for (Pet petCollectionOldPet : petCollectionOld) {
                if (!petCollectionNew.contains(petCollectionOldPet)) {
                    petCollectionOldPet.setIdOwner(null);
                    petCollectionOldPet = em.merge(petCollectionOldPet);
                }
            }
            for (Pet petCollectionNewPet : petCollectionNew) {
                if (!petCollectionOld.contains(petCollectionNewPet)) {
                    Owner oldIdOwnerOfPetCollectionNewPet = petCollectionNewPet.getIdOwner();
                    petCollectionNewPet.setIdOwner(owner);
                    petCollectionNewPet = em.merge(petCollectionNewPet);
                    if (oldIdOwnerOfPetCollectionNewPet != null && !oldIdOwnerOfPetCollectionNewPet.equals(owner)) {
                        oldIdOwnerOfPetCollectionNewPet.getPetCollection().remove(petCollectionNewPet);
                        oldIdOwnerOfPetCollectionNewPet = em.merge(oldIdOwnerOfPetCollectionNewPet);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = owner.getId();
                if (findOwner(id) == null) {
                    System.out.println("The owner with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Owner owner = null;
            try {
                owner = em.getReference(Owner.class, id);
                owner.getId();
            } catch (EntityNotFoundException enfe) {
                System.out.println("The owner with id " + id + " no longer exists.");
            }
            Person idPerson = owner.getIdPerson();
            if (idPerson != null) {
                idPerson.getOwnerCollection().remove(owner);
                idPerson = em.merge(idPerson);
            }
            Collection<Pet> petCollection = owner.getPetCollection();
            for (Pet petCollectionPet : petCollection) {
                petCollectionPet.setIdOwner(null);
                petCollectionPet = em.merge(petCollectionPet);
            }
            em.remove(owner);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Owner> findOwnerEntities() {
        return findOwnerEntities(true, -1, -1);
    }

    public List<Owner> findOwnerEntities(int maxResults, int firstResult) {
        return findOwnerEntities(false, maxResults, firstResult);
    }

    private List<Owner> findOwnerEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Owner.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Owner findOwner(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Owner.class, id);
        } finally {
            em.close();
        }
    }
    
    public Owner findOwnerEntitiesByNameOrSsn(String word){
        EntityManager em=getEntityManager();
        Query query= em.createQuery("select o from Owner o where o.idPerson.name=:name or o.idPerson.ssn=:ssn").setParameter("name", word).setParameter("ssn", word);
        if(!query.getResultList().isEmpty()) {
            return (Owner) query.getSingleResult();
        }
        else{
            return null;
        }
    }

    public int getOwnerCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Owner> rt = cq.from(Owner.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
